// ============================================
// 20 - 面向对象编程特性 (OOP Features)
// ============================================

/// Rust 不是传统的面向对象语言，但提供了许多 OOP 特性

// ==================== 封装 ====================

/// 封装 - 隐藏实现细节
pub struct AveragedCollection {
    list: Vec<i32>,
    average: f64,
}

impl AveragedCollection {
    pub fn new() -> AveragedCollection {
        AveragedCollection {
            list: vec![],
            average: 0.0,
        }
    }
    
    pub fn add(&mut self, value: i32) {
        self.list.push(value);
        self.update_average();
    }
    
    pub fn remove(&mut self) -> Option<i32> {
        let result = self.list.pop();
        match result {
            Some(value) => {
                self.update_average();
                Some(value)
            }
            None => None,
        }
    }
    
    pub fn average(&self) -> f64 {
        self.average
    }
    
    fn update_average(&mut self) {
        let total: i32 = self.list.iter().sum();
        self.average = total as f64 / self.list.len() as f64;
    }
}

pub fn encapsulation() {
    println!("\n=== 封装 ===");
    
    let mut collection = AveragedCollection::new();
    collection.add(10);
    collection.add(20);
    collection.add(30);
    
    println!("平均值: {}", collection.average());
    
    collection.remove();
    println!("移除后平均值: {}", collection.average());
}

// ==================== 继承 ====================

/// Rust 没有传统意义上的继承
/// 使用 trait 和组合代替
pub fn inheritance_alternative() {
    println!("\n=== 继承的替代方案 ===");
    
    println!("Rust 不支持类继承，但提供:");
    println!("1. Trait - 行为共享");
    println!("2. 默认实现 - 代码复用");
    println!("3. 组合 - 结构体嵌套");
    println!("4. Trait 对象 - 多态");
}

// ==================== 多态 ====================

/// 使用 Trait 对象实现多态
pub trait Draw {
    fn draw(&self);
}

pub struct Screen {
    pub components: Vec<Box<dyn Draw>>,
}

impl Screen {
    pub fn run(&self) {
        for component in self.components.iter() {
            component.draw();
        }
    }
}

pub struct Button {
    pub width: u32,
    pub height: u32,
    pub label: String,
}

impl Draw for Button {
    fn draw(&self) {
        println!("绘制按钮: {} ({}x{})", self.label, self.width, self.height);
    }
}

pub struct TextField {
    pub width: u32,
    pub height: u32,
    pub placeholder: String,
}

impl Draw for TextField {
    fn draw(&self) {
        println!("绘制文本框: {} ({}x{})", self.placeholder, self.width, self.height);
    }
}

pub fn polymorphism() {
    println!("\n=== 多态 ===");
    
    let screen = Screen {
        components: vec![
            Box::new(Button {
                width: 50,
                height: 10,
                label: String::from("确定"),
            }),
            Box::new(TextField {
                width: 100,
                height: 20,
                placeholder: String::from("请输入..."),
            }),
            Box::new(Button {
                width: 50,
                height: 10,
                label: String::from("取消"),
            }),
        ],
    };
    
    screen.run();
}

// ==================== 状态模式 ====================

/// 状态模式
pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}

impl Post {
    pub fn new() -> Post {
        Post {
            state: Some(Box::new(Draft {})),
            content: String::new(),
        }
    }
    
    pub fn add_text(&mut self, text: &str) {
        self.content.push_str(text);
    }
    
    pub fn content(&self) -> &str {
        self.state.as_ref().unwrap().content(self)
    }
    
    pub fn request_review(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.request_review())
        }
    }
    
    pub fn approve(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.approve())
        }
    }
}

trait State {
    fn request_review(self: Box<Self>) -> Box<dyn State>;
    fn approve(self: Box<Self>) -> Box<dyn State>;
    fn content<'a>(&self, _post: &'a Post) -> &'a str {
        ""
    }
}

struct Draft {}

impl State for Draft {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        Box::new(PendingReview {})
    }
    
    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }
}

struct PendingReview {}

impl State for PendingReview {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }
    
    fn approve(self: Box<Self>) -> Box<dyn State> {
        Box::new(Published {})
    }
}

struct Published {}

impl State for Published {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }
    
    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }
    
    fn content<'a>(&self, post: &'a Post) -> &'a str {
        &post.content
    }
}

pub fn state_pattern() {
    println!("\n=== 状态模式 ===");
    
    let mut post = Post::new();
    
    post.add_text("今天午饭吃了沙拉");
    println!("草稿内容: '{}'", post.content());
    
    post.request_review();
    println!("审核中内容: '{}'", post.content());
    
    post.approve();
    println!("发布后内容: '{}'", post.content());
}

// ==================== 建造者模式 ====================

/// 建造者模式
#[derive(Debug)]
pub struct Config {
    host: String,
    port: u16,
    timeout: u64,
    debug: bool,
}

pub struct ConfigBuilder {
    host: String,
    port: u16,
    timeout: u64,
    debug: bool,
}

impl ConfigBuilder {
    pub fn new() -> Self {
        ConfigBuilder {
            host: String::from("localhost"),
            port: 8080,
            timeout: 30,
            debug: false,
        }
    }
    
    pub fn host(mut self, host: &str) -> Self {
        self.host = host.to_string();
        self
    }
    
    pub fn port(mut self, port: u16) -> Self {
        self.port = port;
        self
    }
    
    pub fn timeout(mut self, timeout: u64) -> Self {
        self.timeout = timeout;
        self
    }
    
    pub fn debug(mut self, debug: bool) -> Self {
        self.debug = debug;
        self
    }
    
    pub fn build(self) -> Config {
        Config {
            host: self.host,
            port: self.port,
            timeout: self.timeout,
            debug: self.debug,
        }
    }
}

pub fn builder_pattern() {
    println!("\n=== 建造者模式 ===");
    
    let config = ConfigBuilder::new()
        .host("127.0.0.1")
        .port(3000)
        .timeout(60)
        .debug(true)
        .build();
    
    println!("配置: {:?}", config);
}

// ==================== 工厂模式 ====================

/// 工厂模式
pub trait Animal {
    fn make_sound(&self) -> String;
}

pub struct Dog;
pub struct Cat;

impl Animal for Dog {
    fn make_sound(&self) -> String {
        String::from("汪汪!")
    }
}

impl Animal for Cat {
    fn make_sound(&self) -> String {
        String::from("喵喵!")
    }
}

pub struct AnimalFactory;

impl AnimalFactory {
    pub fn create_animal(animal_type: &str) -> Box<dyn Animal> {
        match animal_type {
            "dog" => Box::new(Dog),
            "cat" => Box::new(Cat),
            _ => panic!("未知动物类型"),
        }
    }
}

pub fn factory_pattern() {
    println!("\n=== 工厂模式 ===");
    
    let dog = AnimalFactory::create_animal("dog");
    let cat = AnimalFactory::create_animal("cat");
    
    println!("狗: {}", dog.make_sound());
    println!("猫: {}", cat.make_sound());
}

// ==================== 策略模式 ====================

/// 策略模式
pub trait PaymentStrategy {
    fn pay(&self, amount: f64);
}

pub struct CreditCard {
    number: String,
}

impl PaymentStrategy for CreditCard {
    fn pay(&self, amount: f64) {
        println!("使用信用卡 {} 支付 {} 元", self.number, amount);
    }
}

pub struct PayPal {
    email: String,
}

impl PaymentStrategy for PayPal {
    fn pay(&self, amount: f64) {
        println!("使用 PayPal ({}) 支付 {} 元", self.email, amount);
    }
}

pub struct ShoppingCart {
    payment: Box<dyn PaymentStrategy>,
}

impl ShoppingCart {
    pub fn new(payment: Box<dyn PaymentStrategy>) -> Self {
        ShoppingCart { payment }
    }
    
    pub fn checkout(&self, amount: f64) {
        self.payment.pay(amount);
    }
}

pub fn strategy_pattern() {
    println!("\n=== 策略模式 ===");
    
    let cart1 = ShoppingCart::new(Box::new(CreditCard {
        number: String::from("1234-5678-9012-3456"),
    }));
    cart1.checkout(100.0);
    
    let cart2 = ShoppingCart::new(Box::new(PayPal {
        email: String::from("user@example.com"),
    }));
    cart2.checkout(200.0);
}

// ==================== 观察者模式 ====================

/// 观察者模式
pub trait Observer {
    fn update(&self, message: &str);
}

pub struct EmailNotifier {
    email: String,
}

impl Observer for EmailNotifier {
    fn update(&self, message: &str) {
        println!("发送邮件到 {}: {}", self.email, message);
    }
}

pub struct SmsNotifier {
    phone: String,
}

impl Observer for SmsNotifier {
    fn update(&self, message: &str) {
        println!("发送短信到 {}: {}", self.phone, message);
    }
}

pub struct Subject {
    observers: Vec<Box<dyn Observer>>,
}

impl Subject {
    pub fn new() -> Self {
        Subject {
            observers: Vec::new(),
        }
    }
    
    pub fn attach(&mut self, observer: Box<dyn Observer>) {
        self.observers.push(observer);
    }
    
    pub fn notify(&self, message: &str) {
        for observer in &self.observers {
            observer.update(message);
        }
    }
}

pub fn observer_pattern() {
    println!("\n=== 观察者模式 ===");
    
    let mut subject = Subject::new();
    
    subject.attach(Box::new(EmailNotifier {
        email: String::from("user@example.com"),
    }));
    
    subject.attach(Box::new(SmsNotifier {
        phone: String::from("138-0000-0000"),
    }));
    
    subject.notify("重要通知：系统将在今晚维护");
}

// ==================== 装饰器模式 ====================

/// 装饰器模式
pub trait Coffee {
    fn cost(&self) -> f64;
    fn description(&self) -> String;
}

pub struct SimpleCoffee;

impl Coffee for SimpleCoffee {
    fn cost(&self) -> f64 {
        10.0
    }
    
    fn description(&self) -> String {
        String::from("简单咖啡")
    }
}

pub struct MilkDecorator {
    coffee: Box<dyn Coffee>,
}

impl Coffee for MilkDecorator {
    fn cost(&self) -> f64 {
        self.coffee.cost() + 2.0
    }
    
    fn description(&self) -> String {
        format!("{}, 加奶", self.coffee.description())
    }
}

pub struct SugarDecorator {
    coffee: Box<dyn Coffee>,
}

impl Coffee for SugarDecorator {
    fn cost(&self) -> f64 {
        self.coffee.cost() + 1.0
    }
    
    fn description(&self) -> String {
        format!("{}, 加糖", self.coffee.description())
    }
}

pub fn decorator_pattern() {
    println!("\n=== 装饰器模式 ===");
    
    let coffee = SimpleCoffee;
    println!("{}: {} 元", coffee.description(), coffee.cost());
    
    let coffee = MilkDecorator {
        coffee: Box::new(SimpleCoffee),
    };
    println!("{}: {} 元", coffee.description(), coffee.cost());
    
    let coffee = SugarDecorator {
        coffee: Box::new(MilkDecorator {
            coffee: Box::new(SimpleCoffee),
        }),
    };
    println!("{}: {} 元", coffee.description(), coffee.cost());
}

// ==================== OOP 最佳实践 ====================

/// OOP 在 Rust 中的最佳实践
pub fn oop_best_practices() {
    println!("\n=== OOP 最佳实践 ===");
    
    println!("1. 优先使用组合而非继承");
    println!("2. 使用 trait 定义共享行为");
    println!("3. 使用 trait 对象实现运行时多态");
    println!("4. 使用泛型和 trait bound 实现编译时多态");
    println!("5. 合理使用封装保护内部状态");
    println!("6. 考虑使用类型系统而非设计模式");
    println!("7. 利用 Rust 的所有权系统设计 API");
}

/// 主函数 - 演示所有功能
#[allow(dead_code)]
pub fn main() {
    println!("╔════════════════════════════════════════╗");
    println!("║   Rust 面向对象编程教程                ║");
    println!("╚════════════════════════════════════════╝");
    
    encapsulation();
    inheritance_alternative();
    polymorphism();
    state_pattern();
    builder_pattern();
    factory_pattern();
    strategy_pattern();
    observer_pattern();
    decorator_pattern();
    oop_best_practices();
    
    println!("\n✅ 面向对象编程教程完成！");
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_averaged_collection() {
        let mut collection = AveragedCollection::new();
        collection.add(10);
        collection.add(20);
        assert_eq!(collection.average(), 15.0);
    }
    
    #[test]
    fn test_post_state() {
        let mut post = Post::new();
        post.add_text("test");
        assert_eq!(post.content(), "");
        
        post.request_review();
        assert_eq!(post.content(), "");
        
        post.approve();
        assert_eq!(post.content(), "test");
    }
    
    #[test]
    fn test_builder() {
        let config = ConfigBuilder::new()
            .host("localhost")
            .port(8080)
            .build();
        assert_eq!(config.host, "localhost");
        assert_eq!(config.port, 8080);
    }
}

